
class ModWindow {
  Mod parentMod;
  //Panel parentPanel;
  int mode, index;
  float bx, by, wx, wy;
  PGraphics canvas, click;
  int cm, cp, cw, oGx, oGy, aGx, aGy;
  Select selector;
  int modGrab=0;
  Boolean areaGrab=false;
  Boolean makeWire=false;
  Boolean modSel=false;
  Boolean wireSel=false;
  Boolean selection=false;
  Boolean hasFocus;
  int[] newWire;
  float mx, my, gox, goy, bs, selX, selY;

  ModWindow(float tempBx, float tempBy, float tempWx, float tempWy, int tempIndex) {
    bx=tempBx;
    by=tempBy;
    wx=tempWx;
    wy=tempWy;
    index=tempIndex;
    canvas=createGraphics((int)wx, (int)wy, JAVA2D);
    click=createGraphics((int)wx, (int)wy, P2D);
    mode=-1;
    newWire = new int[3];
  }
  void setParent(Mod tempMod) {
    parentMod=tempMod;
    mode=0;
    selector=new Select(parentMod);
    areaGrab=false;
  }
  void drawAll() {
    if (mode==0) { //Module
      mx=mouseX-bx;
      my=mouseY-by;

      if (areaGrab) {

        parentMod.gx=oGx-(aGx-(int)mx);
        parentMod.gy=oGy-(aGy-(int)my);
      }
      if (modGrab!=0) {
        selector.moveSel(mx-gox, my-goy, modGrab-1);
      }
      canvas.beginDraw();
      canvas.textFont(font, 10);
      canvas.background(100);
      canvas.smooth();
      int tgx=parentMod.gx;
      int tgy=parentMod.gy;
      for (int i=parentMod.im-1;i>=0;i--) {
        if (!parentMod.mods[i].markedForDelete) {
          parentMod.mods[i].pgx=tgx;
          parentMod.mods[i].pgy=tgy;
          parentMod.mods[i].drawWires(canvas);
          parentMod.mods[i].drawMod(canvas);
        }
      }
      if (makeWire) {
        canvas.noFill();
        canvas.strokeWeight(3);
        canvas.strokeCap(ROUND);
        println("nW: "+newWire[0]);
        if (newWire[2]==0) {
          canvas.stroke(sysCl[parentMod.mods[newWire[0]].oPs[newWire[1]].type], 64);
          selX=parentMod.mods[newWire[0]].bx+parentMod.mods[newWire[0]].oPs[newWire[1]].bx+parentMod.gx;
          selY=parentMod.mods[newWire[0]].by+parentMod.mods[newWire[0]].oPs[newWire[1]].by+parentMod.gy;
          bs=(abs(selX-mx)/curveD)+(abs(selY-my)/curveD);
          canvas.bezier(selX, selY, selX+bs, selY, mx-bs, my, mx, my);
        }
        else if (newWire[2]==1) {
          canvas.stroke(sysCl[parentMod.mods[newWire[0]].iPs[newWire[1]-128].type], 64);
          selX=parentMod.mods[newWire[0]].bx+parentMod.mods[newWire[0]].iPs[newWire[1]-128].bx+parentMod.gx;
          selY=parentMod.mods[newWire[0]].by+parentMod.mods[newWire[0]].iPs[newWire[1]-128].by+parentMod.gy;
          bs=(abs(selX-mx)/curveD)+(abs(selY-my)/curveD);
          canvas.bezier(selX, selY, selX-bs, selY, mx+bs, my, mx, my);
        }
        else if (newWire[2]==2) {
          canvas.stroke(sysCl[parentMod.mods[newWire[0]].fIP.type], 64);
          selX=parentMod.mods[newWire[0]].bx+parentMod.mods[newWire[0]].fIP.bx+parentMod.gx;
          selY=parentMod.mods[newWire[0]].by+parentMod.mods[newWire[0]].fIP.by+parentMod.gy;
          bs=(abs(selX-mx)/(curveD*2))+(abs(selY-my)/curveD);
          canvas.bezier(selX, selY, selX, selY+bs, mx, my+bs, mx, my);
        }
        else if (newWire[2]==3) {
          canvas.stroke(sysCl[parentMod.mods[newWire[0]].fOP.type], 64);
          selX=parentMod.mods[newWire[0]].bx+parentMod.mods[newWire[0]].fOP.bx+parentMod.gx;
          selY=parentMod.mods[newWire[0]].by+parentMod.mods[newWire[0]].fOP.by+parentMod.gy;
          bs=(abs(selX-mx)/(curveD*2))+(abs(selY-my)/curveD);
          canvas.bezier(selX, selY, selX, selY+bs, mx, my+bs, mx, my);
        }
      }
      color hcl = click.get(int(mx), int(my));
      int hcm=int(red(hcl));
      int hcp=int(green(hcl));
      int hcw=int(blue(hcl));
      //debug="PNode:"+parentIndex+" Module:"+hcm+"  Port:"+hcp+"  Wire:"+hcw;



      if (hcm!=0 && hcp!=0 && hcw==0) {
        canvas.fill(255, 255, 255);
        if (hcp>129 && hcp!=255) {
          parentMod.mods[hcm-1].iPs[hcp-129].nameAlpha=200;
        }
        else if (hcp<127) {
          println(hcp);
          parentMod.mods[hcm-1].oPs[hcp-1].nameAlpha=200;
        }
      }
      canvas.fill(255);
      canvas.textAlign(LEFT);
      String longname;
      longname=parentMod.name;
      canvas.text(parentMod.name, 10, wy-10);
      canvas.noFill();
      canvas.strokeWeight(1);
      canvas.stroke(255);
      canvas.rect(0, 0, wx-1, wy-1);
      canvas.endDraw();
      image(canvas, bx, by);
      click.beginDraw();
      click.background(0);
      for (int i=parentMod.im-1;i>=0;i--) {
        if (!parentMod.mods[i].markedForDelete) {
          parentMod.mods[i].drawModClick(click);
          parentMod.mods[i].drawWiresClick(click);
        }
      }
      click.endDraw();
    }
  }
  void pressed() {
    if (mouseButton==LEFT) {
      color cl = click.get(int(mx), int(my));
      cm=int(red(cl));
      cp=int(green(cl));
      cw=int(blue(cl));
      println(cp);

      //debug="Module:"+cm+" Port:"+cp+" Wire:"+cw;
      if (cm!=0) {
        if (cp!=0) {
          if (cw!=0) {
            //wire
            if (keyPressed && keyCode==17) {
              selector.addWireSel(cm, cp, cw);
            }
            else {
              selector.setWireSel(cm, cp, cw);
            }
          }
          else {
            //port
            newWire[0]=cm-1;
            newWire[1]=cp-1;
            if (cp==128) { //feed in
              newWire[2]=2;
              makeWire=true;
            }
            else if (cp>128) {
              if (cp==255) {
                newWire[2]=3;
                makeWire=true;
              }
              else {
                if (!parentMod.mods[newWire[0]].iPs[newWire[1]-128].isUsed) {
                  newWire[2]=1;
                  makeWire=true;
                }
              }
            }
            else {
              newWire[2]=0;
              makeWire=true;
            }
          }
        }
        else {
          modGrab=cm;
          gox=mx-parentMod.mods[modGrab-1].bx;
          goy=my-parentMod.mods[modGrab-1].by;
          if (keyPressed && keyCode==17) {
            selector.addModSel(cm);
          }
          else {
            selector.setModSel(cm);
          }
        }
      }
      else {
        //area move
        if (keyPressed) {

          if (keyCode == 17) {
          }
        }
        else {
          selector.doClearAll();
          areaGrab=true;
          oGx=parentMod.gx;
          oGy=parentMod.gy;
          aGx=int(mouseX-bx);
          aGy=int(mouseY-by);
        }
      }
    }
    else if (mouseButton==RIGHT) {
    }
  }
  void released() {
    if (mouseButton==LEFT) {
      modGrab=0;
      areaGrab=false;
      selection=false;
      color cl = click.get(int(mx), int(my));
      cm=int(red(cl));
      cp=int(green(cl));
      cw=int(blue(cl));
      if (makeWire) {

        if (cm!=0 && cp!=0 && cw==0) {
          if (newWire[0]!=cm-1) {

            //not same device
            if (newWire[2]==0 && cp>128 && !parentMod.mods[cm-1].iPs[cp-129].isUsed) { //out port to in port. in port not in use
              makeNewWire(parentMod.mods[newWire[0]].oPs[newWire[1]], parentMod.mods[cm-1].iPs[cp-129]);
            }
            if (newWire[2]==1 && cp<128) {
              makeNewWire(parentMod.mods[cm-1].oPs[cp-1], parentMod.mods[newWire[0]].iPs[newWire[1]-128]);
            }
            if (newWire[2]==2 && cp==255 && !parentMod.mods[cm-1].fOP.isUsed) { //out port to in port. in port not in use
              makeNewWire(parentMod.mods[newWire[0]].fIP, parentMod.mods[cm-1].fOP);
            }
            if (newWire[2]==3 && cp==128) {
              makeNewWire(parentMod.mods[cm-1].fIP, parentMod.mods[newWire[0]].fOP);
            }
          }
        }
      }

      makeWire=false;
      if (cm!=0 && cp==0 && cw==1) {
        selector.doClearAll();
        uic[0].setParent(parentMod.mods[cm-1]);
      }
    }
    else if (mouseButton==RIGHT) {
    }
  }
  void makeNewWire(outPort start, inPort end) {
    if (!start.isConnected(end.parent.index, end.index)) {  //not already connected
      if (!end.parent.isInChain(start.parent.index)) {
        if (start.type!=0 && start.type<=2 && end.type==0) {  //set port type from out port
          end.type=start.type;
        }
        if (start.type==0 && end.type!=0 && end.type<=2) {  //set port type from in port
          start.type=end.type;
        }
        if (start.type==end.type && end.type!=0) { //if type matches make wire
          //addPorts
          if (end.addPort) {

            end.parent.addNewPort(end.index-129, 0);
          }
          if (start.addPort) {
            start.parent.addNewPort(start.index-1, 1);
          }

          start.addWire(end);
          end.parent.callOnEdit();
          start.parent.callOnEdit();
          start.parent.update(start.index);
          parentMod.beginStackAll();
        }
      }
    }
  }

  void keyPress(int key) {
    println(keyCode+" "+key+ " "+ char(key));
    if (selector.ms==1 && parentMod.mods[selector.modSelected[0]].isValue && parentMod.mods[selector.modSelected[0]].isInput) {
      if (parentMod.mods[selector.modSelected[0]].oPs[0].type==0) {
        if (key>47 && key<58) {
          parentMod.mods[selector.modSelected[0]].oPs[0].type=2;
        }
        else {
          parentMod.mods[selector.modSelected[0]].oPs[0].type=1;
        }
      }
      if (parentMod.mods[selector.modSelected[0]].oPs[0].type==2) {
        String iS=parentMod.mods[selector.modSelected[0]].name;
        if ((iS.equals("") || iS.equals("0")) && key== DELETE) {
          selector.deleteAll();
          parentMod.beginStackAll();
        }
        else {

          iS=floatInput(key, iS);
          parentMod.mods[selector.modSelected[0]].name=iS;
          if (iS.equals("") && parentMod.mods[selector.modSelected[0]].oPs[0].ws==0 && parentMod.mods[selector.modSelected[0]].oPs[0].anyIn) {
            parentMod.mods[selector.modSelected[0]].oPs[0].type=0;
          }
          parentMod.mods[selector.modSelected[0]].setWx(20+iS.length()*6);
          parentMod.mods[selector.modSelected[0]].sendFloat(float(parentMod.mods[selector.modSelected[0]].name), 0);
        }
      }
      else if (parentMod.mods[selector.modSelected[0]].oPs[0].type==1) {
        String iS=parentMod.mods[selector.modSelected[0]].name;
        if (iS.equals("") && key== DELETE) {
          selector.deleteAll();
          parentMod.beginStackAll();
        }
        else {
          iS=stringInput(key, iS);
          parentMod.mods[selector.modSelected[0]].name=iS;
          if (iS.equals("") && parentMod.mods[selector.modSelected[0]].oPs[0].ws==0 && parentMod.mods[selector.modSelected[0]].oPs[0].anyIn) {
            parentMod.mods[selector.modSelected[0]].oPs[0].type=0;
          }
          parentMod.mods[selector.modSelected[0]].setWx(20+iS.length()*6);
          parentMod.mods[selector.modSelected[0]].sendString(parentMod.mods[selector.modSelected[0]].name, 0);
        }
      }
    }
    else {
      if (key == CONTROL) {
      }
      if (key== DELETE) {
        selector.deleteAll();
        parentMod.beginStackAll();
      }
      if (key=='p' || key=='P') {
        //println(mC[parentIndex].mods[0].stack);
      }
      if (key=='R') {
        uic[0].setParent(rootMod);
      }
      if (key=='H') {
        parentMod.hideUnusedPorts=!parentMod.hideUnusedPorts;
        for (int i=0;i<parentMod.im;i++) {
          parentMod.mods[i].updatePorts();
        }
      }
    }
  }
}

